package org.lx.nursing.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.huaweicloud.sdk.iotda.v5.IoTDAClient;
import com.huaweicloud.sdk.iotda.v5.model.DeviceShadowData;
import com.huaweicloud.sdk.iotda.v5.model.ShowDeviceShadowRequest;
import com.huaweicloud.sdk.iotda.v5.model.ShowDeviceShadowResponse;
import lombok.extern.slf4j.Slf4j;
import org.lx.common.constant.HttpStatus;
import org.lx.common.exception.base.BaseException;
import org.lx.common.utils.DateUtils;
import org.lx.common.utils.StringUtils;
import org.lx.common.utils.UserThreadLocal;
import org.lx.framework.web.service.TokenService;
import org.lx.nursing.domain.*;
import org.lx.nursing.dto.ElderInfoDTO;
import org.lx.nursing.dto.UserLoginRequestDto;
import org.lx.nursing.mapper.*;
import org.lx.nursing.service.IFamilyMemberService;
import org.lx.nursing.service.WechatService;
import org.lx.nursing.vo.ElderFamilyBindVO;
import org.lx.nursing.vo.FamilyMemberElderVo;
import org.lx.nursing.vo.LoginVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.*;


/**
 * 老人家属Service业务层处理
 *
 * @author sewen
 * @date 2025-03-05
 */

@Service
@Slf4j
public class FamilyMemberServiceImpl extends ServiceImpl<FamilyMemberMapper, FamilyMember> implements IFamilyMemberService {
    static List<String> DEFAULT_NICKNAME_PREFIX = ListUtil.of(
            "花开富贵",
            "笑面人生",
            "日富一日",
            "好柿开花",
            "柿柿如意",
            "一椰暴富",
            "大柚所为",
            "杨梅吐气",
            "天生荔枝"
    );
    @Autowired
    private FamilyMemberMapper familyMemberMapper;
    @Autowired
    private ElderFamilyRelationMapper elderFamilyRelationMapper;
    @Autowired
    private RoomMapper roomMapper;
    @Autowired
    private BedMapper bedMapper;
    @Autowired
    private DeviceMapper deviceMapper;
    @Autowired
    private WechatService wechatService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private ElderMapper elderMapper;
    @Autowired
    private DeviceDataMapper deviceDataMapper;
    @Resource
    private IoTDAClient client;

    /**
     * 小程序端登录
     *
     * @param userLoginRequestDto
     * @return
     */
    @Override
    public LoginVo login(UserLoginRequestDto userLoginRequestDto) {
        String openId = wechatService.getOpenid(userLoginRequestDto.getCode());
        FamilyMember familyMember = getOne(Wrappers.lambdaQuery(FamilyMember.class)
                .eq(FamilyMember::getOpenId, openId));
        if (ObjectUtil.isEmpty(familyMember)) {
            familyMember = FamilyMember.builder().openId(openId).build();
        }

        //调用微信api获取用户绑定的手机号
        String phone = wechatService.getPhone(userLoginRequestDto.getPhoneCode());

        //保存或修改用户
        saveOrUpdateFamilyMember(familyMember, phone);

        // 存入token,返回
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", familyMember.getId());
        claims.put("nickName", familyMember.getName());

        String token = tokenService.createToken(claims);
        LoginVo loginVo = new LoginVo();
        loginVo.setToken(token);
        loginVo.setNickName(familyMember.getName());
        return loginVo;
    }

    @Override
    public boolean bindElder(ElderInfoDTO dto) {
        Long familyMemberId = UserThreadLocal.getUserId();
        //根据dto中的身份证号查询该老人是否已经被绑定
        Elder elder = elderMapper.selectOne(Wrappers.lambdaQuery(Elder.class)
                .eq(Elder::getIdCardNo, dto.getIdCard()));
        if (ObjectUtil.isEmpty(elder)) {
            //抛出异常老人不存在
            throw new RuntimeException("老人不存在");
        }
        //根据老人id查询老人和家属关系
        ElderFamilyRelation elderFamilyRelation = elderFamilyRelationMapper.selectOne(Wrappers.lambdaQuery(ElderFamilyRelation.class)
                .eq(ElderFamilyRelation::getElderId, elder.getId()));
        if (ObjectUtil.isNotEmpty(elderFamilyRelation)) {
            throw new RuntimeException("老人已绑定");
        }
        //根据familyMemberId查询性别
        FamilyMember familyMember = familyMemberMapper.selectById(familyMemberId);
        Integer sex = familyMember.getGender();
        if (ObjectUtil.isEmpty(sex)) {
            sex = 1;
        }
        ElderFamilyRelation elderFamilyRelation1 = ElderFamilyRelation.builder()
                .elderId(elder.getId())
                .familyMemberId(familyMemberId)
                .relationType(sex.toString())
                .remark(dto.getRemark())
                .createTime(DateUtils.getNowDate())
                .build();
        int insert = elderFamilyRelationMapper.insert(elderFamilyRelation1);
        return insert > 0;
    }

    @Override
    public List<ElderFamilyBindVO> listByPage(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        Long familyMemberId = UserThreadLocal.getUserId();
        //构建返回vo
        List<ElderFamilyBindVO> list = new ArrayList<>();
        //从关系表中查
        List<ElderFamilyRelation> efList = elderFamilyRelationMapper.selectAllElderByFamilyMemberId(familyMemberId);
        //循环取出老人id
        List<Long> elderIds = new ArrayList<>();
        for (ElderFamilyRelation elderFamilyRelation : efList) {
            elderIds.add(elderFamilyRelation.getElderId());
        }

        for (Long elderId : elderIds) {
            list.add(getElderFamilyBindVO(elderId));
        }

        return list;
    }

    public ElderFamilyBindVO getElderFamilyBindVO(Long elderId) {
        ElderFamilyBindVO elderFamilyBindVO = new ElderFamilyBindVO();
        //查询出有关系的所有信息
        Elder elder = elderMapper.selectById(elderId);
        ElderFamilyRelation elderFamilyRelation = elderFamilyRelationMapper.selectOne(new LambdaQueryWrapper<ElderFamilyRelation>().eq(ElderFamilyRelation::getElderId, elderId));
        //根据老人表中的bedid查
        Bed bed = bedMapper.selectOne(new LambdaQueryWrapper<Bed>().eq(Bed::getBedNumber, elder.getBedNumber()));
        Room room = roomMapper.selectOne(new LambdaQueryWrapper<Room>().eq(Room::getId, bed.getRoomId()));
        LambdaQueryWrapper<Device> deviceLambdaQueryWrapper = new LambdaQueryWrapper<>();
        log.info("=======老人id{}", elderId);
        deviceLambdaQueryWrapper.eq(Device::getLocationType, 0);
        deviceLambdaQueryWrapper.eq(Device::getBindingLocation, elderId);
        Device device = deviceMapper.selectOne(deviceLambdaQueryWrapper);
        //构建返回值
        elderFamilyBindVO.setMid(elderFamilyRelation.getId());
        elderFamilyBindVO.setMremark(elderFamilyRelation.getRemark());
        elderFamilyBindVO.setElderId(elderId);
        elderFamilyBindVO.setName(elder.getName());
        elderFamilyBindVO.setImage(elder.getImage());
        elderFamilyBindVO.setBedNumber(elder.getBedNumber());
        elderFamilyBindVO.setTypeName(room.getTypeName());
        if (ObjectUtil.isNotEmpty(device)) {
            elderFamilyBindVO.setIotId(device.getIotId());
            elderFamilyBindVO.setDeviceName(device.getDeviceName());
            elderFamilyBindVO.setProductKey(device.getProductKey());
        }
        return elderFamilyBindVO;
    }

    /**
     * 保存或修改客户
     *
     * @param member
     * @param phone
     */
    private void saveOrUpdateFamilyMember(FamilyMember member, String phone) {

        // 1.判断取到的手机号与数据库中保存的手机号不一样
        if (ObjectUtil.notEqual(phone, member.getPhone())) {
            // 修改手机号
            member.setPhone(phone);
        }
        // 2.判断id存在，则修改
        if (ObjectUtil.isNotEmpty(member.getId())) {
            updateById(member);
            return;
        }
        // id不存在，保存新用户
        // 随机组装昵称，词组+手机号后四位
        String nickName = DEFAULT_NICKNAME_PREFIX.get((int) (Math.random() * DEFAULT_NICKNAME_PREFIX.size()))
                + StringUtils.substring(member.getPhone(), 7);

        member.setName(nickName);
        save(member);
    }

    @Override
    public List<?> queryServiceProperties(String iotId) {
        ShowDeviceShadowRequest request = new ShowDeviceShadowRequest();
        request.setDeviceId(iotId);
        ShowDeviceShadowResponse response = client.showDeviceShadow(request);
        if (response.getHttpStatusCode() != HttpStatus.SUCCESS) {
            throw new BaseException("物联网接口-查询设备上报数据, 调用失败");
        }
        List<DeviceShadowData> shadowData = response.getShadow();
        if (CollUtil.isEmpty(shadowData)) {
            return Collections.emptyList();
        }

        JSONObject jsonObject = JSONUtil.parseObj(shadowData.get(0).getReported().getProperties());
        List<Map<String, Object>> list = new ArrayList<>();
        LocalDateTime activeTime = LocalDateTimeUtil.parse(shadowData.get(0).getReported().getEventTime(),
                "yyyyMMdd'T'HHmmss'Z'");
        LocalDateTime eventTime = activeTime.atZone(ZoneId.from(ZoneOffset.UTC))
                .withZoneSameInstant(ZoneId.of("Asia/Shanghai"))
                .toLocalDateTime();
        jsonObject.forEach((k, v) -> {
            Map<String, Object> map = new HashMap<>();
            map.put("functionId", k);
            map.put("eventTime", eventTime);
            map.put("value", v);
            list.add(map);
        });
        return list;
    }

    @Override
    public List<?> queryDeviceDataListByDay(String iotId, String functionId, Long startTime, Long endTime) {
        //把时间戳转换成时间
        LocalDateTime startDateTime = LocalDateTimeUtil.of(startTime);
        LocalDateTime endDateTime = LocalDateTimeUtil.of(endTime);
        List<Map<String, Object>> data = deviceDataMapper.selectDeviceDataListByDay(iotId, functionId, startDateTime, endDateTime);
        return data;
    }

    @Override
    public List<?> queryDeviceDataListByWeek(String iotId, String functionId, Long startTime, Long endTime) {
        LocalDateTime startDateTime = LocalDateTimeUtil.of(startTime);
        LocalDateTime endDateTime = LocalDateTimeUtil.of(endTime);
        List<Map<String, Object>> data = deviceDataMapper.selectDeviceDataListByWeek(iotId, functionId, startDateTime, endDateTime);
        return data;
    }

    @Override
    public List<FamilyMemberElderVo> getMyFamilyMember() {
        Long familyMemberId = UserThreadLocal.getUserId();
        return familyMemberMapper.getMyFamilyMember(familyMemberId);
    }

}
